﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YArchitech.Controls;
using YJKCoordinate;

namespace SetPipe.Utiltiy
{
	public class InputDataStack
	{
		public InputDataStack(Document m_doc)
		{
			this.m_doc = m_doc;
			this.ResetStack();
		}

		public List<ThreePipeInputDataPacker> GetResult()
		{
			return this.lstThreePointInputData;
		}

		public TwoPipeInputDataPakcer GetTwoInputDataPacker(int index = 0)
		{
			if (this.lstTwoPointInputData.Count - 1 >= index)
			{
				return this.lstTwoPointInputData[index];
			}
			return null;
		}

		internal void ResetStack()
		{
			this.deleteDetailCures(true);
			this.lstPoints.Clear();
			this.lstOnePointInputData.Clear();
			this.lstTwoPointInputData.Clear();
			this.lstThreePointInputData.Clear();
			this.lstMakedListCurves.Clear();
			this.lstMakedDetailCurves.Clear();
			this.nowPointIndex = -1;
		}

		public XYZ GetEndPoint()
		{
			if (0 >= this.lstPoints.Count)
			{
				return null;
			}
			return this.lstPoints[this.lstPoints.Count - 1];
		}

		public void AddOnePoint(OnePipeInputDataPacker onePoint)
		{
			if (onePoint == null)
			{
				return;
			}
			if (0 < this.lstPoints.Count && onePoint.GetPoint(0).IsAlmostEqualTo(this.lstPoints[this.lstPoints.Count - 1]))
			{
				return;
			}
			if (!this.avoidExceptionPoint(onePoint))
			{
				return;
			}
			if (!this.checkInput(onePoint))
			{
				YJKMessageBox.Show(StaticRescource.StrMessage_InputNear);
				this.RemoveOne();
				return;
			}
			if (!this.InputTestException(onePoint))
			{
				YJKMessageBox.Show(StaticRescource.StrMessage_WrongInput);
				return;
			}
			this.lstPoints.Add(onePoint.GetPoint(0));
			this.lstOnePointInputData.Add(onePoint);
			this.nowPointIndex++;
			if (this.nowPointIndex == 0)
			{
				this.allStartPoint = onePoint.GetPoint(0);
			}
			if (1 <= this.nowPointIndex)
			{
				this.lstTwoPointInputData.Add(new TwoPipeInputDataPakcer(this.lstOnePointInputData[this.nowPointIndex - 1], onePoint));
			}
			if (2 == this.nowPointIndex)
			{
				this.lstThreePointInputData.Add(new ThreePipeInputDataPacker(this.lstTwoPointInputData[0], this.lstTwoPointInputData[1], null, false));
			}
			else if (2 < this.nowPointIndex)
			{
				int count = this.lstTwoPointInputData.Count;
				int count2 = this.lstThreePointInputData.Count;
				this.lstThreePointInputData.Add(new ThreePipeInputDataPacker(this.lstTwoPointInputData[count - 2], this.lstTwoPointInputData[count - 1], this.lstThreePointInputData[count2 - 1].GetEndPoint(), false));
			}
			this.makeAndDrawNewCurve(true, false, false);
		}

		public void SetEnd(bool ifEnd)
		{
			if (0 < this.lstThreePointInputData.Count)
			{
				this.lstThreePointInputData[this.lstThreePointInputData.Count - 1].SetEnd(ifEnd);
				this.makeAndDrawNewCurve(true, false, false);
			}
		}

		public void DeleteAllDetailCurves()
		{
			this.deleteDetailCures(true);
		}

		private void RemoveOne()
		{
			this.clearTemplst();
			if (-1 == this.nowPointIndex)
			{
				return;
			}
			this.deleteDetailCures(false);
			if (2 <= this.nowPointIndex)
			{
				this.lstPoints.RemoveAt(this.nowPointIndex);
				this.lstOnePointInputData.RemoveAt(this.nowPointIndex);
				this.lstTwoPointInputData.RemoveAt(this.lstTwoPointInputData.Count - 1);
				this.lstThreePointInputData.RemoveAt(this.lstThreePointInputData.Count - 1);
			}
			else if (1 == this.nowPointIndex)
			{
				this.lstPoints.RemoveAt(this.nowPointIndex);
				this.lstOnePointInputData.RemoveAt(this.nowPointIndex);
				this.lstTwoPointInputData.RemoveAt(this.lstTwoPointInputData.Count - 1);
			}
			else
			{
				this.lstPoints.RemoveAt(this.nowPointIndex);
				this.lstOnePointInputData.RemoveAt(this.nowPointIndex);
			}
			this.nowPointIndex--;
			this.makeTemplst();
		}

		private void makeAndDrawNewCurve(bool ifDraw = true, bool ifIsEnd = false, bool hasSetEnd = false)
		{
			this.clearTemplst();
			if (0 >= this.nowPointIndex)
			{
				return;
			}
			if (1 == this.nowPointIndex)
			{
				List<XYZ> list = new List<XYZ>();
				List<Curve> list2 = new List<Curve>();
				list2 = Utiltiy.GetNormalLineBoundryCurves(this.lstTwoPointInputData[0].GetPoint(0), this.lstTwoPointInputData[0].GetPoint(1), this.lstTwoPointInputData[0].GetPipeParameters(1), ref list);
				list2.AddRange(list2);
				this.lstMakedListCurves.Add(list2);
				List<DetailCurve> list3 = new List<DetailCurve>();
				Transaction transaction = new Transaction(this.m_doc, "creat");
				transaction.Start();
				foreach (Curve curve in list2)
				{
					DetailCurve item = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve);
					list3.Add(item);
				}
				transaction.Commit();
				this.lstMakedDetailCurves.Add(list3);
				return;
			}
			if (1 < this.nowPointIndex)
			{
				if (!ifIsEnd)
				{
					if (2 == this.nowPointIndex)
					{
						Transaction transaction2 = new Transaction(this.m_doc, "tempDelete");
						transaction2.Start();
						foreach (DetailCurve detailCurve in this.lstMakedDetailCurves[0])
						{
							this.m_doc.Delete(detailCurve.Id);
						}
						transaction2.Commit();
						this.lstMakedDetailCurves[0] = new List<DetailCurve>();
					}
					int index = this.lstThreePointInputData.Count - 1;
					List<Curve> list4 = new List<Curve>();
					foreach (PipeBoundryCurvePakcer pipeBoundryCurvePakcer in this.lstThreePointInputData[index].GetLstBoundryCurvePacker())
					{
						list4.AddRange(pipeBoundryCurvePakcer.LstBoundryCurves);
					}
					this.lstMakedListCurves.Add(list4);
					List<DetailCurve> list5 = new List<DetailCurve>();
					Transaction transaction3 = new Transaction(this.m_doc, "creat");
					transaction3.Start();
					foreach (Curve curve2 in list4)
					{
						DetailCurve item2 = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve2);
						list5.Add(item2);
					}
					transaction3.Commit();
					this.lstMakedDetailCurves.Add(list5);
					if (!hasSetEnd)
					{
						this.makeTemplst();
						return;
					}
				}
				else
				{
					this.deleteDetailCures(false);
					this.makeAndDrawNewCurve(true, false, true);
				}
			}
		}

		private void deleteDetailCures(bool ifAll = true)
		{
			this.clearTemplst();
			if (!ifAll && 1 <= this.nowPointIndex)
			{
				this.lstMakedListCurves.RemoveAt(this.lstMakedListCurves.Count - 1);
				Transaction transaction = new Transaction(this.m_doc, "delete");
				transaction.Start();
				foreach (DetailCurve detailCurve in this.lstMakedDetailCurves[this.lstMakedDetailCurves.Count - 1])
				{
					this.m_doc.Delete(detailCurve.Id);
				}
				transaction.Commit();
				this.lstMakedDetailCurves.RemoveAt(this.lstMakedDetailCurves.Count - 1);
				if (2 == this.nowPointIndex)
				{
					List<DetailCurve> list = new List<DetailCurve>();
					Transaction transaction2 = new Transaction(this.m_doc, "creat");
					transaction2.Start();
					foreach (Curve curve in this.lstMakedListCurves[0])
					{
						DetailCurve item = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve);
						list.Add(item);
					}
					transaction2.Commit();
					this.lstMakedDetailCurves[0] = list;
					return;
				}
			}
			else if (ifAll)
			{
				this.lstMakedListCurves.Clear();
				Transaction transaction3 = new Transaction(this.m_doc, "delete");
				transaction3.Start();
				foreach (List<DetailCurve> list2 in this.lstMakedDetailCurves)
				{
					foreach (DetailCurve detailCurve2 in list2)
					{
						this.m_doc.Delete(detailCurve2.Id);
					}
				}
				transaction3.Commit();
				this.lstMakedDetailCurves.Clear();
			}
		}

		private void makeTemplst()
		{
			if (0 >= this.lstThreePointInputData.Count)
			{
				return;
			}
			int index = this.lstThreePointInputData.Count - 1;
			List<XYZ> list = new List<XYZ>();
			List<Curve> list2 = new List<Curve>();
			if (!this.lstThreePointInputData[index].GetEndPoint().IsAlmostEqualTo(this.lstPoints[this.nowPointIndex]))
			{
				list2.AddRange(Utiltiy.GetNormalLineBoundryCurves(this.lstThreePointInputData[index].GetEndPoint(), this.lstPoints[this.nowPointIndex], this.lstThreePointInputData[index].GetPipeParameters(1), ref list));
			}
			this.lstTempCurve = list2;
			Transaction transaction = new Transaction(this.m_doc, "creat");
			transaction.Start();
			foreach (Curve curve in this.lstTempCurve)
			{
				this.lstTempDCurve.Add(this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve));
			}
			transaction.Commit();
		}

		private void clearTemplst()
		{
			this.lstTempCurve.Clear();
			Transaction transaction = new Transaction(this.m_doc, "delete");
			transaction.Start();
			foreach (DetailCurve detailCurve in this.lstTempDCurve)
			{
				this.m_doc.Delete(detailCurve.Id);
			}
			transaction.Commit();
			this.lstTempDCurve.Clear();
		}

		private bool checkInput(OnePipeInputDataPacker input)
		{
			if (0 >= this.nowPointIndex)
			{
				return true;
			}
			List<XYZ> list = new List<XYZ>();
			bool result;
			if (2 <= this.nowPointIndex)
			{
				list = new List<XYZ>();
				list.Add(input.GetPoint(0));
				list.Add(this.lstPoints[this.nowPointIndex]);
				result = this.nowChecker.PipeIfCanUse(list, input.CornerKinde, input.GetPipeParameters(0));
			}
			else
			{
				list = new List<XYZ>();
				list.Add(input.GetPoint(0));
				list.AddRange(this.lstPoints);
				result = this.nowChecker.PipeIfCanUse(list, input.CornerKinde, input.GetPipeParameters(0));
			}
			return result;
		}

		private bool InputTestException(OnePipeInputDataPacker input)
		{
			try
			{
				if (this.lstPoints.Count >= 2)
				{
					TwoPipeInputDataPakcer inputTwo = new TwoPipeInputDataPakcer(this.lstOnePointInputData[this.lstOnePointInputData.Count - 1], input);
					if (this.lstPoints.Count == 2)
					{
						new ThreePipeInputDataPacker(this.lstTwoPointInputData[this.lstTwoPointInputData.Count - 1], inputTwo, null, false);
					}
					else
					{
						new ThreePipeInputDataPacker(this.lstTwoPointInputData[this.lstTwoPointInputData.Count - 1], inputTwo, this.lstThreePointInputData[this.lstThreePointInputData.Count - 1].GetEndPoint(), false);
					}
				}
			}
			catch (CornerMakerException)
			{
				return false;
			}
			return true;
		}

		private bool avoidExceptionPoint(OnePipeInputDataPacker input)
		{
			if (0 >= this.lstTwoPointInputData.Count)
			{
				return true;
			}
			XYZ endPoint = this.lstTwoPointInputData[this.lstTwoPointInputData.Count - 1].GetLine(0).GetEndPoint(1);
			XYZ endPoint2 = this.lstTwoPointInputData[this.lstTwoPointInputData.Count - 1].GetLine(1).GetEndPoint(1);
			return !input.GetPoint(0).IsAlmostEqualTo(endPoint) && !input.GetPoint(0).IsAlmostEqualTo(endPoint2);
		}

		private Document m_doc;

		private List<XYZ> lstPoints = new List<XYZ>();

		public List<OnePipeInputDataPacker> lstOnePointInputData = new List<OnePipeInputDataPacker>();

		private List<TwoPipeInputDataPakcer> lstTwoPointInputData = new List<TwoPipeInputDataPakcer>();

		private List<ThreePipeInputDataPacker> lstThreePointInputData = new List<ThreePipeInputDataPacker>();

		private List<List<Curve>> lstMakedListCurves = new List<List<Curve>>();

		private List<List<DetailCurve>> lstMakedDetailCurves = new List<List<DetailCurve>>();

		private List<Curve> lstTempCurve = new List<Curve>();

		private List<DetailCurve> lstTempDCurve = new List<DetailCurve>();

		private XYZ allStartPoint;

		private int nowPointIndex = -1;

		private PipeIChecker nowChecker = new PipeInputChecker();
	}
}
